from fastapi import Depends, HTTPException, status, APIRouter
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from src.database.db import get_db
from src.models.user_models import User, Captcha
from src.utils.utils import hash_password, verify_password
from src.config.configs import settings
from datetime import timedelta, datetime
from jose import JWTError, jwt
from pydantic import BaseModel
from src.auth.captcha import generate_captcha
import uuid


router = APIRouter()

class Token(BaseModel):
    access_token: str
    token_type: str = "bearer"

class UserCreate(BaseModel):
    username: str
    email: str
    password: str

class CaptchaResponse(BaseModel):
    captcha_id: str
    image_data: str

class LoginRequest(BaseModel):
    username: str
    password: str
    captcha_id: str
    captcha_code: str

@router.post("/captcha", response_model=CaptchaResponse)
async def get_captcha(db: Session = Depends(get_db)):
    """获取验证码"""
    # 生成验证码
    code, image_data = generate_captcha()
    
    # 生成唯一ID
    captcha_id = str(uuid.uuid4())
    
    # 存储验证码到数据库
    db_captcha = Captcha(
        username=None,  # 登录前不知道用户名
        code=code,
        is_used=False
    )
    db.add(db_captcha)
    db.commit()
    db.refresh(db_captcha)
    
    return {
        "captcha_id": str(db_captcha.id),
        "image_data": image_data
    }

def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.access_token_expire_minutes)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, settings.secret_key, algorithm=settings.algorithm)
    return encoded_jwt

@router.post("/register", status_code=status.HTTP_201_CREATED)
async def register(user: UserCreate, db: Session = Depends(get_db)):
    db_user = db.query(User).filter(User.username == user.username).first()
    if db_user:
        raise HTTPException(status_code=400, detail="Username already registered")

    hashed_password = hash_password(user.password)
    db_user = User(username=user.username, email=user.email, hashed_password=hashed_password)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return {"message": "User created successfully"}

@router.post("/token", response_model=Token)
async def login_for_access_token(
    request: LoginRequest, 
    db: Session = Depends(get_db)
):
    """带验证码的登录接口"""
    # 1. 验证验证码
    captcha = db.query(Captcha).filter(
        Captcha.id == request.captcha_id,
        Captcha.is_used == False,
        Captcha.created_at >= datetime.utcnow() - timedelta(minutes=5)  # 5分钟内有效
    ).first()
    
    if not captcha or captcha.code.lower() != request.captcha_code.lower():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid captcha",
        )
    
    # 标记验证码为已使用
    captcha.is_used = True
    db.commit()
    
    # 2. 验证用户
    user = db.query(User).filter(User.username == request.username).first()
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    if not verify_password(request.password, user.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # 3. 生成token
    access_token_expires = timedelta(minutes=settings.access_token_expire_minutes)
    access_token = create_access_token(
        data={"sub": user.username}, 
        expires_delta=access_token_expires
    )
    
    return {"access_token": access_token, "token_type": "bearer"}